﻿#include "mediaStreamIO.h"
#include "error.h"
#include "ioQueue.h"
#include "global.h"

#include <QDebug>

#include <crtdbg.h>
#include <assert.h>

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif

class mediaStreamIOPrivate {
public:
    AVFormatContext *ic  = NULL;
    ioQueue         *queue = new ioQueue;

    __int64         seekPos = 0;
    bool            isExit = true;

	~mediaStreamIOPrivate() {
		delete queue;
	}
};

mediaStreamIO::mediaStreamIO(QObject *parent) :
    QThread(parent)
{
    d = new mediaStreamIOPrivate;
}

mediaStreamIO::~mediaStreamIO()
{
    stopRead();
    delete d;
}

void mediaStreamIO::setFormat(AVFormatContext *format)
{
    d->ic = format;
}

void mediaStreamIO::seek(long long pos)
{
    d->seekPos = pos;
}

ioQueue *mediaStreamIO::getQueue()
{
    return d->queue;
}

void mediaStreamIO::stopRead()
{
    if (d->isExit)
        return ;

    d->isExit = true;

    while (this->isRunning()) {
        QThread::msleep(30);
    }

    d->queue->clear();
}

void mediaStreamIO::initQueue()
{
    for(unsigned int i = 0; i < d->ic->nb_streams; i++)
    {
        if (AVMEDIA_TYPE_VIDEO == d->ic->streams[i]->codec->codec_type) {
            d->queue->appendQueue(MediaType::ioV, i);
        } else if (AVMEDIA_TYPE_AUDIO == d->ic->streams[i]->codec->codec_type) {
            d->queue->appendQueue(MediaType::ioA, i);
        } else if (AVMEDIA_TYPE_SUBTITLE == d->ic->streams[i]->codec->codec_type) {
            d->queue->appendQueue(MediaType::ioS, i);
        }
    }
}

void mediaStreamIO::run()
{
    //TODO: 线程过程可能会失败，所以，稍后要监视线程过程状态

    if(NULL == d->ic){
        _err = "文件可能未打开";
        return ;
    }

    //初始化队列
    this->initQueue();

    AVPacket *pkt = new AVPacket;
    int ret = -1;
    d->isExit = false;
    while (!d->isExit)
    {
        ret = av_read_frame(d->ic, pkt);
        if(ret < 0) {
            if (ret == AVERROR_EOF || avio_feof(d->ic->pb)) {
                break;
            }
        }
        d->queue->enqueue(pkt);
        QThread::msleep(30);
    }
    delete pkt;
    qDebug()<<"mediaStreamIO exit";
}

